import datetime

from util.dateutil import date_str
from x_pc.db.common import Session
from x_pc.db.common.model import WorkType, WopsWaveletOrder, ParameterConfigDtl, SelfProductVehiclePlan, VehicleTask
from x_pc.exceptions import PcException


class ParameterConfigDtlService(object):

    @staticmethod
    def get_data() -> list[ParameterConfigDtl]:
        with Session() as sess:
            return sess.query(ParameterConfigDtl).all()

    @staticmethod
    def get_group_data(group_code: str) -> list[ParameterConfigDtl]:
        with Session() as sess:
            return sess.query(ParameterConfigDtl).filter(
                ParameterConfigDtl.parameter_configgroup_code == group_code).all()

    @staticmethod
    def get_group_code_data(group_code: str, code: str) -> ParameterConfigDtl:
        with Session() as sess:
            return sess.query(ParameterConfigDtl).filter(
                ParameterConfigDtl.parameter_configgroup_code == group_code).filter(
                ParameterConfigDtl.code == code).first()


class WorkTypeService(object):
    """
    工作类型
    """

    @staticmethod
    def get_data() -> list[WorkType]:
        with Session() as sess:
            return sess.query(WorkType).all()


class WaveletOrderService(object):

    @staticmethod
    def get_data(date_list: list[datetime.date], datetime_list: list[datetime.datetime]) -> tuple[
        list[str], list[tuple[str, str]], list[tuple[datetime.datetime, datetime.datetime]]]:
        """
        :param date_list: 波次日期 (存在跨天场景 可能多个日期)
        :param datetime_list: 排程数据日期
        :return:
        """
        date_list = [_.date() if isinstance(_, datetime.datetime) else _ for _ in date_list]
        with Session() as sess:
            order_list = sess.query(WopsWaveletOrder).filter(WopsWaveletOrder.work_date.in_(date_list)).all()
        if not order_list:
            raise PcException(f'[PC] 数据库表wops_wavelet_order，未查询到小波次数据 date: {date_list}')
        #
        result_list = []
        for d in datetime_list:
            oid = None
            for o in order_list:
                if o.plan_begin <= d < o.plan_end:
                    oid = o.id
                    break
            result_list.append(oid)
        order_list.sort(key=lambda x: x.plan_begin)
        raw_order_date_list = [(_.plan_begin, _.plan_end) for _ in order_list]
        order_date_list = sorted([(date_str(_.plan_begin), date_str(_.plan_end)) for _ in order_list])
        return result_list, order_date_list, raw_order_date_list

    @staticmethod
    def get_base_time() -> tuple:
        date_now = datetime.datetime.now().strftime('%Y-%m-%d')
        with Session() as sess:
            run_wavelet_order: WopsWaveletOrder = sess.query(WopsWaveletOrder).filter(
                WopsWaveletOrder.work_date == date_now).filter(WopsWaveletOrder.state == 2).first()
            if run_wavelet_order:
                return run_wavelet_order.plan_end, run_wavelet_order.id
            else:
                return None, None

    @staticmethod
    def prev_wavelet_order_id():
        """
        获取前一个波次ID
        - 一般为当前时间 seq-1
        - 若seq=0，则查找前一天的seq最大值
        """
        date_now = datetime.datetime.now().strftime('%Y-%m-%d')
        with Session() as sess:
            run_wavelet_order: WopsWaveletOrder = sess.query(WopsWaveletOrder).filter(
                WopsWaveletOrder.work_date == date_now).filter(WopsWaveletOrder.state == 2).first()
            if run_wavelet_order:
                seq = run_wavelet_order.seq
                if seq > 0:
                    prev_wavelet_order: WopsWaveletOrder = sess.query(WopsWaveletOrder).filter(
                        WopsWaveletOrder.work_date == date_now).filter(WopsWaveletOrder.seq == (seq - 1)).first()
                    if prev_wavelet_order:
                        return prev_wavelet_order.id
                else:
                    prev_date = (datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d')
                    prev_wavelet_order: WopsWaveletOrder = sess.query(WopsWaveletOrder).filter(
                        WopsWaveletOrder.work_date == prev_date).order_by(WopsWaveletOrder.seq.desc()).first()
                    if prev_wavelet_order:
                        return prev_wavelet_order.id
        return None


class SelfProductVehiclePlanService(object):

    @staticmethod
    def get_vehicle_list(work_date_list: list[str]) -> list[SelfProductVehiclePlan]:
        """
        查询某工作时间下的 自制车时间区间
        :param work_date_list:
        :return:
        """
        if not work_date_list:
            return []
        with Session() as sess:
            return sess.query(SelfProductVehiclePlan).filter(
                SelfProductVehiclePlan.work_date.in_(work_date_list)
            ).order_by(SelfProductVehiclePlan.plan_begin.asc()).all()


class VehicleTaskService(object):

    @staticmethod
    def get_assigned_ports_dict(work_date_list: list[str]) -> dict[str, int]:
        """
        查询 车次-> 分配的出货口 数量
        :param work_date_list:
        :return:
        """
        if not work_date_list:
            return {}
        with Session() as sess:
            data_list: list[VehicleTask] = sess.query(VehicleTask).filter(
                VehicleTask.work_date.in_(work_date_list)
            ).order_by(VehicleTask.plan_begin.asc()).all()
        ports_dict = {}
        for data in data_list:
            ports_dict[data.deliver_factory_code] = data.ems_port_nums()
        return ports_dict
